home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2000 #1 / Amiga Plus CD - 2000 - No. 1.iso / Tools / Dev / Meshwriter / imagine.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-12-03  |  29.2 KB  |  919 lines

  1. /*
  2. **      $VER: imagine.c 1.00 (27.03.1999)
  3. **
  4. **      Creation date : 17.11.1998
  5. **
  6. **      Description       :
  7. **         Standart saver module for meshwriter.library.
  8. **         Saves the mesh as Imagine TDDD file.
  9. **
  10. **
  11. **      Written by Stephan Bielmann
  12. **
  13. */
  14.  
  15. /*************************** Includes *******************************/
  16.  
  17. /*
  18. ** Amiga includes
  19. */
  20.  
  21. #include <clib/dos_protos.h>
  22.  
  23. /*
  24. ** Project includes
  25. */
  26. #include "meshwriter_private.h"
  27. #include "utilities.h"
  28.  
  29. /**************************** Defines *******************************/
  30.  
  31. /*
  32. ** Number of elements in the buffers
  33. */
  34. #define Ci_BUFFERC 99    // color buffer must be dividable by 3 !
  35. #define Ci_BUFFERV 100    // vector buffer
  36. #define Ci_BUFFERE 100    // edge buffer must be dividable by 4 !
  37. #define Ci_BUFFERF 99    // face buffer must be dividable by 3 !
  38.  
  39. /*********************** Type definitions ***************************/
  40.  
  41. /*
  42. ** Private type definitions
  43. */
  44. typedef struct {
  45.     LONG x,y,z;
  46. } TDDDVector;
  47.  
  48. typedef struct {
  49.     UBYTE name[4];
  50.     ULONG size;
  51. } TDDDChunk;
  52.  
  53. typedef struct {
  54.     TDDDChunk chunk;
  55.     UBYTE oname[18];
  56. } TDDDNameChunk;
  57.  
  58. typedef struct {
  59.     TDDDChunk chunk;
  60.     UWORD shape;
  61.     UWORD lamp;
  62. } TDDDShapChunk;
  63.  
  64. typedef struct {
  65.     TDDDChunk chunk;
  66.     TDDDVector vector;
  67. } TDDDVectorChunk;
  68.  
  69. typedef struct {
  70.     TDDDChunk chunk;
  71.     TDDDVector xaxis,yaxis,zaxis;
  72. } TDDDAxisChunk;
  73.  
  74. typedef struct {
  75.     TDDDChunk chunk;
  76.     TDDDVector mins,maxs;
  77. } TDDDBBoxChunk;
  78.  
  79. typedef struct {
  80.     TDDDChunk chunk;
  81.     UWORD count;
  82. } TDDDCountChunk;
  83.  
  84. typedef struct {
  85.     TDDDChunk chunk;
  86.     ULONG count;
  87. } TDDDCountChunk2;
  88.  
  89. typedef struct {
  90.     TDDDChunk chunk;
  91.     UBYTE pad;
  92.     UBYTE r,g,b;
  93. } TDDDColorChunk;
  94.  
  95. /********************** Private functions ***************************/
  96.  
  97. /********************************************************************\
  98. *                                                                    *
  99. * Name         : float2long                                          *
  100. *                                                                    *
  101. * Description  : Converts a float value into an Imagine long value.  *
  102. *                                                                    *
  103. * Arguments    : f IN : The float value to convert.                  *
  104. *                                                                    *
  105. * Return Value : The converted value as LONG                         *
  106. *                                                                    *
  107. * Comment      :                                                     *
  108. *                                                                    *
  109. \********************************************************************/
  110. static LONG float2long(TOCLFloat f) {
  111.     if (f<0) return(-(LONG)(-65536.0*f+0.5));
  112.     else return((LONG)(65536.0*f+0.5));
  113. }
  114.  
  115. /********************** Public functions ****************************/
  116.  
  117. /********************************************************************\
  118. *                                                                    *
  119. * Name         : write3TDDD                                          *
  120. *                                                                    *
  121. * Description  : Writes a standart imagine < 3.0 binary file.        *
  122. *                                                                    *
  123. * Arguments    : tdddfile IN : An already opened file stream.        *
  124. *                mesh     IN : Pointer to the mesh.                  *
  125. *                                                                    *
  126. * Return Value : RCNOERROR                                           *
  127. *                RCWRITEDATA                                         *
  128. *                                                                    *
  129. * Comment      : Default material is white !                         *
  130. *                                                                    *
  131. \********************************************************************/
  132. ULONG write3TDDD(BPTR tdddfile, TOCLMesh *mesh) {
  133.     TDDDChunk            form,obj,desc,tobj;
  134.     TDDDNameChunk        name;
  135.     TDDDAxisChunk        axis;
  136.     TDDDShapChunk        shap;
  137.     TDDDVectorChunk    posi,size;
  138.     TDDDBBoxChunk        bbox;
  139.     TDDDCountChunk        pnts,edge,face,clst,tlst;    
  140.     TDDDColorChunk        colr,refl,tran,spc1;
  141.     
  142.     TOCLPolygonNode            *pln=NULL;
  143.     TOCLPolygonsVerticesNode    *plvi=NULL,*plv1=NULL,*plv2=NULL,*plv3=NULL;
  144.     TOCLVertexNode                *ver=NULL;
  145.     TOCLMaterialNode            *mat=NULL;    
  146.  
  147.     TDDDVector            vbuffer[Ci_BUFFERV];    // Ci_BUFFERV * sizeof(TDDDVector)    vector buffer
  148.     UWORD                ebuffer[Ci_BUFFERE];    // Ci_BUFFERE * sizeof(UWORD)            edge buffer
  149.     UWORD                fbuffer[Ci_BUFFERF];    // Ci_BUFFERF * sizeof(UWORD)            face buffer
  150.     UBYTE                cbuffer[Ci_BUFFERC];    // Ci_BUFFERB                            byte buffer
  151.     ULONG                bufferstate;
  152.     ULONG                edgeoffset;
  153.  
  154. // werte check fract : -32767.5 bis 32767.5 => neuer rueckgabe wert !!
  155. // counts nicht groesser als 32k !!
  156.  
  157.     /*
  158.     ** Initializing all chunks and theyr sizes and static contents
  159.     */
  160.     setUBYTEArray(name.chunk.name,"NAME",4);
  161.     name.chunk.size = 18;     // fixed size
  162.     setUBYTEArray(name.oname,mesh->name,18);
  163.  
  164.     setUBYTEArray(shap.chunk.name,"SHAP",4);
  165.     shap.chunk.size=4;     // fixed size
  166.     shap.shape=2;            // an axis object
  167.     shap.lamp=0;            // not a lamp
  168.  
  169.     setUBYTEArray(posi.chunk.name,"POSI",4);
  170.     posi.chunk.size=12;                    // fixed size
  171.     posi.vector.x=float2long(0.0);        // origin of the object is fixed to {0,0,0}
  172.     posi.vector.y=float2long(0.0);
  173.     posi.vector.z=float2long(0.0);
  174.  
  175.     setUBYTEArray(axis.chunk.name,"AXIS",4);
  176.     axis.chunk.size=36;                            // fixed size
  177.     axis.xaxis.x=1,axis.xaxis.y=0,axis.xaxis.z=0;    // fixed x-axis unit vector
  178.     axis.yaxis.x=0,axis.yaxis.y=1,axis.yaxis.z=0;    // fixed y-axis unit vector
  179.     axis.zaxis.x=0,axis.zaxis.y=0,axis.zaxis.z=1;    // fixwd z-axis unit vector
  180.  
  181.     setUBYTEArray(size.chunk.name,"SIZE",4);
  182.     size.chunk.size=12;                                                // fixed size
  183.     size.vector.x=float2long(mesh->bBox.right - mesh->bBox.left);    // bbox length x axis
  184.     size.vector.y=float2long(mesh->bBox.front - mesh->bBox.rear);    // bbox length y axis
  185.     size.vector.z=float2long(mesh->bBox.top - mesh->bBox.bottom);    // bbox length z axis
  186.  
  187.     setUBYTEArray(bbox.chunk.name,"BBOX",4);
  188.     bbox.chunk.size=24;                            // fixed size
  189.     bbox.mins.x=float2long(mesh->bBox.left);        // bbox min x size
  190.     bbox.mins.y=float2long(mesh->bBox.rear);        // bbox min y size
  191.     bbox.mins.z=float2long(mesh->bBox.bottom);    // bbox min z size
  192.     bbox.maxs.x=float2long(mesh->bBox.right);        // bbox max x size
  193.     bbox.maxs.y=float2long(mesh->bBox.front);        // bbox max y size
  194.     bbox.maxs.z=float2long(mesh->bBox.top);        // bbox max z size
  195.  
  196.     setUBYTEArray(pnts.chunk.name,"PNTS",4);
  197.     // number of points = number of vertices
  198.     pnts.count=mesh->vertices.numberOfVertices;
  199.     pnts.chunk.size=sizeof(pnts.count) + pnts.count * sizeof(TDDDVector);    
  200.  
  201.     // number of faces = sum of each polygon (number of vertices - 2)
  202.     // number of edges = sum of each polygon ((number of vertices-3)*2 +3)
  203.     face.count=0;
  204.     edge.count=0;
  205.       if(mesh->polygons.firstNode!=NULL) {                 
  206.         pln=mesh->polygons.firstNode;
  207.         do {
  208.             // we accept only polygons with 3 or more points !
  209.             if (pln->numberOfVertices>=3) {
  210.                 face.count+=pln->numberOfVertices-2;
  211.                 edge.count+=(pln->numberOfVertices-3)*2+3;
  212.             }
  213.             pln=pln->next;
  214.         } while (pln!=NULL);
  215.     } 
  216.  
  217.     setUBYTEArray(face.chunk.name,"FACE",4);
  218.     face.chunk.size=sizeof(face.count) + face.count * 3 * sizeof(UWORD);
  219.     
  220.     setUBYTEArray(edge.chunk.name,"EDGE",4);
  221.     edge.chunk.size=sizeof(edge.count) + edge.count * 2 * sizeof(UWORD);
  222.  
  223.     setUBYTEArray(colr.chunk.name,"COLR",4);
  224.     colr.chunk.size=4;                    // fixed size
  225.     colr.pad=0;                        // default value
  226.     colr.r=255,colr.g=255,colr.b=255;    // default color is white
  227.  
  228.     setUBYTEArray(refl.chunk.name,"REFL",4);
  229.     refl.chunk.size=4;                        // fixed size
  230.     refl.pad=0;                            // default value
  231.     refl.r=0,colr.g=0,colr.b=0;            // default reflection is black
  232.  
  233.     setUBYTEArray(tran.chunk.name,"TRAN",4);
  234.     tran.chunk.size=4;                        // fixed size
  235.     tran.pad=0;                            // default value
  236.     tran.r=0,colr.g=0,colr.b=0;            // default transparency is none
  237.  
  238.     setUBYTEArray(spc1.chunk.name,"SPC2",4);
  239.     spc1.chunk.size=4;                    // fixed size
  240.     spc1.pad=0;                        // default value
  241.     spc1.r=255,colr.g=255,colr.b=255;    // default specularity is white
  242.  
  243.     setUBYTEArray(clst.chunk.name,"CLST",4);
  244.     // each face has its color so count = #faces
  245.     clst.count=face.count;
  246.     clst.chunk.size=sizeof(clst.count) + clst.count * 3 * sizeof(UBYTE);
  247.     // if an odd we have an odd count, size must be incremented to insert a pad
  248.     if (clst.count%2) clst.chunk.size++;
  249.  
  250.     setUBYTEArray(tlst.chunk.name,"TLST",4);
  251.     // each face has its transparency so count = #faces
  252.     tlst.count=face.count;
  253.     tlst.chunk.size=sizeof(tlst.count) + tlst.count * 3 * sizeof(UBYTE);
  254.     // if an odd we have an odd count, size must be incremented to insert a pad
  255.     if (tlst.count%2) tlst.chunk.size++;
  256.  
  257.     setUBYTEArray(desc.name,"DESC",4);
  258.     // size = sizes of all above and the size of themselves, = 8 Bytes each
  259.     // pnts,edge,face only if there are polygons and edges and faces
  260.     // clst,tlst only if there are materials and faces
  261.     
  262.     desc.size = name.chunk.size+axis.chunk.size+shap.chunk.size+posi.chunk.size+size.chunk.size;
  263.     desc.size += bbox.chunk.size+colr.chunk.size+refl.chunk.size+tran.chunk.size+spc1.chunk.size;
  264.     desc.size += 10 * 8;
  265.  
  266.     if(mesh->polygons.firstNode && edge.count && face.count) {
  267.         desc.size += pnts.chunk.size+edge.chunk.size+face.chunk.size;
  268.         desc.size += 3 * 8;
  269.     }
  270.     if(mesh->materials.firstNode && face.count) {
  271.         desc.size += clst.chunk.size+tlst.chunk.size;
  272.         desc.size += 2 * 8;
  273.     }
  274.  
  275.     setUBYTEArray(obj.name,"OBJ ",4);
  276.     // size = desc.size + 8 for desc itself and 8 for tobj
  277.     obj.size = desc.size + 16;
  278.  
  279.     setUBYTEArray(form.name,"FORM",4);
  280.     // size = obj.size + 8 for obj itself and 4 for tddd
  281.     form.size = obj.size + 12;
  282.  
  283.     setUBYTEArray(tobj.name,"TOBJ",4);
  284.     tobj.size=0;        // fixed size
  285.  
  286.  
  287.     /*
  288.     ** Writing the chunks and theyr dynamic content
  289.     */
  290.     if(FWrite(tdddfile,&form,sizeof(form),1)!=1) return(RCWRITEDATA);
  291.  
  292.     if(FWrite(tdddfile,"TDDD",1,4)!=4) return(RCWRITEDATA);
  293.     
  294.     if(FWrite(tdddfile,&obj,sizeof(obj),1)!=1) return(RCWRITEDATA);
  295.     
  296.     if(FWrite(tdddfile,&desc,sizeof(desc),1)!=1) return(RCWRITEDATA);
  297.  
  298.     if(FWrite(tdddfile,&name,sizeof(name),1)!=1) return(RCWRITEDATA);
  299.  
  300.     if(FWrite(tdddfile,&shap,sizeof(shap),1)!=1) return(RCWRITEDATA);
  301.  
  302.     if(FWrite(tdddfile,&posi,sizeof(posi),1)!=1) return(RCWRITEDATA);    
  303.  
  304.     if(FWrite(tdddfile,&axis,sizeof(axis),1)!=1) return(RCWRITEDATA);    
  305.  
  306.     if(FWrite(tdddfile,&size,sizeof(size),1)!=1) return(RCWRITEDATA);    
  307.     
  308.     if(FWrite(tdddfile,&bbox,sizeof(bbox),1)!=1) return(RCWRITEDATA);    
  309.  
  310.     // only if there are polygons to write, and edge and faces
  311.     if (mesh->polygons.firstNode && edge.count && face.count) {
  312.         if(FWrite(tdddfile,&pnts,sizeof(pnts),1)!=1) return(RCWRITEDATA);    
  313.  
  314.         // initialize the buffer state
  315.         bufferstate=0;
  316.  
  317.         // write the points
  318.         // this is a futil test but anyway
  319.         if(mesh->vertices.firstNode!=NULL) {
  320.             ver=mesh->vertices.firstNode;
  321.             do {
  322.                 TOCLVertex v=ver->vertex;
  323.  
  324.                 vbuffer[bufferstate].x=float2long(v.x);
  325.                 vbuffer[bufferstate].y=float2long(v.y);
  326.                 vbuffer[bufferstate].z=float2long(v.z);
  327.  
  328.                 // increment the bufferstate and 
  329.                 // check if the buffer is full and write and initialize it
  330.                 if (++bufferstate==Ci_BUFFERV) {
  331.                     if(FWrite(tdddfile,&vbuffer,Ci_BUFFERV*sizeof(TDDDVector),1)!=1) return(RCWRITEDATA);
  332.                     bufferstate=0;
  333.                 }
  334.                 
  335.                 ver=ver->next;
  336.             } while(ver!=NULL);
  337.         
  338.             // write the rest of the buffer if there is any
  339.             if (bufferstate!=0) {
  340.                 if(FWrite(tdddfile,&vbuffer,bufferstate*sizeof(TDDDVector),1)!=1) return(RCWRITEDATA);
  341.             }            
  342.         }
  343.  
  344.         if(FWrite(tdddfile,&edge,sizeof(edge),1)!=1) return(RCWRITEDATA);    
  345.     
  346.         // initialize the buffer state
  347.         bufferstate=0;
  348.  
  349.             pln=mesh->polygons.firstNode;
  350.         do {                                
  351.             // only if there are 3 or more points in the polygon
  352.             if(pln->numberOfVertices>=3) {
  353.                 plv1=pln->firstNode;
  354.             
  355.                 plvi=plv1;
  356.                 do {    
  357.                     plv2=plvi->next;
  358.                     plv3=plv2->next;
  359.                 
  360.                     ebuffer[bufferstate++]=plv1->vertexNode->index-1;
  361.                     ebuffer[bufferstate++]=plv2->vertexNode->index-1;
  362.                     ebuffer[bufferstate++]=plv2->vertexNode->index-1;
  363.                     ebuffer[bufferstate++]=plv3->vertexNode->index-1;
  364.  
  365.                     // check if the buffer is full and write and initialize it
  366.                     if (bufferstate==Ci_BUFFERE) {
  367.                         if(FWrite(tdddfile,&ebuffer,Ci_BUFFERE*sizeof(UWORD),1)!=1) return(RCWRITEDATA);                      
  368.                         bufferstate=0;
  369.                     }
  370.                 
  371.                     plvi=plvi->next;
  372.                 } while(plv3->next!=NULL);    
  373.                     
  374.                 ebuffer[bufferstate++]=plv1->vertexNode->index-1;
  375.                 ebuffer[bufferstate++]=plv3->vertexNode->index-1;
  376.  
  377.                 // write the rest of the buffer
  378.                 if(FWrite(tdddfile,&ebuffer,bufferstate*sizeof(UWORD),1)!=1) return(RCWRITEDATA);                      
  379.                 bufferstate=0;
  380.             }
  381.             pln=pln->next;
  382.         } while(pln!=NULL);
  383.         
  384.         if(FWrite(tdddfile,&face,sizeof(face),1)!=1) return(RCWRITEDATA);    
  385.  
  386.         // initialize the buffer state
  387.         bufferstate=0;
  388.  
  389.         // initialize the edge offset
  390.         edgeoffset=0;
  391.  
  392.         pln=mesh->polygons.firstNode;
  393.         do {                                
  394.             ULONG i;
  395.             
  396.             // only if there are 3 or more points in the polygon
  397.             if(pln->numberOfVertices>=3) {
  398.                   // do this for each edge - 1
  399.                 for(i=0;i<((pln->numberOfVertices-3)*2+2);i+=2) {
  400.                     fbuffer[bufferstate++]=edgeoffset+i;
  401.                     fbuffer[bufferstate++]=edgeoffset+i+1;
  402.                     fbuffer[bufferstate++]=edgeoffset+i+2;
  403.                     
  404.                     // check if the buffer is full and write and initialize it
  405.                     if (bufferstate==Ci_BUFFERF) {
  406.                         if(FWrite(tdddfile,&fbuffer,Ci_BUFFERF*sizeof(UWORD),1)!=1) return(RCWRITEDATA);                      
  407.                         bufferstate=0;
  408.                     }
  409.                 }
  410.                 edgeoffset+=i+1;
  411.             }
  412.             pln=pln->next;
  413.         } while(pln!=NULL);
  414.  
  415.         // write he rest of the buffer if there is any
  416.         if (bufferstate!=0) {
  417.             if(FWrite(tdddfile,&fbuffer,bufferstate*sizeof(UWORD),1)!=1) return(RCWRITEDATA);                      
  418.             bufferstate=0;
  419.         }
  420.     }
  421.     
  422.     if(FWrite(tdddfile,&colr,sizeof(colr),1)!=1) return(RCWRITEDATA);
  423.  
  424.     if(FWrite(tdddfile,&refl,sizeof(refl),1)!=1) return(RCWRITEDATA);
  425.  
  426.     if(FWrite(tdddfile,&tran,sizeof(tran),1)!=1) return(RCWRITEDATA);
  427.     
  428.     if(FWrite(tdddfile,&spc1,sizeof(spc1),1)!=1) return(RCWRITEDATA);
  429.     
  430.     // writing the materials if there are some, and if there are any faces
  431.     if(mesh->materials.firstNode && face.count) {
  432.         if(FWrite(tdddfile,&clst,sizeof(clst),1)!=1) return(RCWRITEDATA);          
  433.  
  434.         // initialize the buffer state
  435.         bufferstate=0;
  436.  
  437.         // The diffuse color, per face
  438.         pln=mesh->polygons.firstNode;
  439.  
  440.         do {
  441.             TOCLColor col=pln->materialNode->diffuseColor;
  442.             // we accept only polygons with 3 or more points !
  443.             if (pln->numberOfVertices>=3) {
  444.                 ULONG i;
  445.                 for(i=0;i<(pln->numberOfVertices-2);i++) {
  446.                     cbuffer[bufferstate++]=col.r;
  447.                     cbuffer[bufferstate++]=col.g;
  448.                     cbuffer[bufferstate++]=col.b;
  449.  
  450.                     // check if the buffer is full and write and initialize it
  451.                     if (bufferstate==Ci_BUFFERC) {
  452.                         if(FWrite(tdddfile,&cbuffer,Ci_BUFFERC*sizeof(UBYTE),1)!=1) return(RCWRITEDATA);
  453.                         bufferstate=0;
  454.                     }
  455.                 }
  456.             }
  457.                         
  458.             pln=pln->next;
  459.         } while(pln!=NULL);
  460.  
  461.         // if we have an odd count a pad has to be added at the end
  462.         if (clst.count%2) {
  463.             cbuffer[bufferstate++]=0;
  464.         }
  465.         
  466.         // write the rest of the buffer if any
  467.         if (bufferstate!=0) {
  468.             if(FWrite(tdddfile,&cbuffer,bufferstate*sizeof(UBYTE),1)!=1) return(RCWRITEDATA);
  469.             bufferstate=0;
  470.         }
  471.  
  472.         if(FWrite(tdddfile,&tlst,sizeof(tlst),1)!=1) return(RCWRITEDATA);          
  473.  
  474.         // initialize the buffer state
  475.         bufferstate=0;
  476.  
  477.         // The transparency, per face
  478.         pln=mesh->polygons.firstNode;
  479.         do {
  480.             // we accept only polygons with 3 or more points !
  481.             if (pln->numberOfVertices>=3) {
  482.                 ULONG i;
  483.                 
  484.                 for(i=0;i<(pln->numberOfVertices-2);i++) {  
  485.                     cbuffer[bufferstate++]=UBYTE(255*mat->transparency);
  486.                     cbuffer[bufferstate++]=UBYTE(255*mat->transparency);
  487.                     cbuffer[bufferstate++]=UBYTE(255*mat->transparency);
  488.  
  489.                     // check if the buffer is full and write and initialize it
  490.                     if (bufferstate==Ci_BUFFERC) {
  491.                         if(FWrite(tdddfile,&cbuffer,Ci_BUFFERC*sizeof(UBYTE),1)!=1) return(RCWRITEDATA);
  492.                         bufferstate=0;
  493.                     }
  494.                 }
  495.             }
  496.             
  497.             pln=pln->next;
  498.         } while(pln!=NULL);
  499.  
  500.         // if we have an odd count a pad has to be added at the end
  501.         if (tlst.count%2) {
  502.             cbuffer[bufferstate++]=0;
  503.         }
  504.         
  505.         // write the rest of the buffer if any
  506.         if (bufferstate!=0) {
  507.             if(FWrite(tdddfile,&cbuffer,bufferstate*sizeof(UBYTE),1)!=1) return(RCWRITEDATA);
  508.             bufferstate=0;
  509.         }
  510.     }
  511.  
  512.     if(FWrite(tdddfile,&tobj,sizeof(tobj),1)!=1) return(RCWRITEDATA);
  513.   
  514.     return(RCNOERROR);
  515. }
  516.  
  517. /********************************************************************\
  518. *                                                                    *
  519. * Name         : write3TDDDH                                         *
  520. *                                                                    *
  521. * Description  : Writes a huge imagine binary file.                  *
  522. *                                                                    *
  523. * Arguments    : tdddfile IN : An already opened file stream.        *
  524. *                mesh     IN : Pointer to the mesh.                  *
  525. *                                                                    *
  526. * Return Value : RCNOERROR                                           *
  527. *                RCWRITEDATA                                         *
  528. *                                                                    *
  529. * Comment      : Default material is white !                         *
  530. *                                                                    *
  531. \********************************************************************/
  532. ULONG write3TDDDH(BPTR tdddfile, TOCLMesh *mesh) {
  533.     TDDDChunk            form,obj,desc,tobj;
  534.     TDDDNameChunk        name;
  535.     TDDDAxisChunk        axis;
  536.     TDDDShapChunk        shp2;
  537.     TDDDVectorChunk    posi,size;
  538.     TDDDBBoxChunk        bbox;
  539.     TDDDCountChunk2    pnt2,edg2,fac2,cls2,tls2;    
  540.     TDDDColorChunk        colr,refl,tran,spc2;
  541.     
  542.     TOCLPolygonNode            *pln=NULL;
  543.     TOCLPolygonsVerticesNode    *plvi=NULL,*plv1=NULL,*plv2=NULL,*plv3=NULL;
  544.     TOCLVertexNode                *ver=NULL;
  545.     TOCLMaterialNode            *mat=NULL;    
  546.  
  547.     TDDDVector            vbuffer[Ci_BUFFERV];    // Ci_BUFFERV * sizeof(TDDDVector)    vector buffer
  548.     ULONG                ebuffer[Ci_BUFFERE];    // Ci_BUFFERE * sizeof(ULONG)            edge buffer
  549.     ULONG                fbuffer[Ci_BUFFERF];    // Ci_BUFFERF * sizeof(ULONG)            face buffer
  550.     UBYTE                bbuffer[Ci_BUFFERC];    // Ci_BUFFERB                            byte buffer
  551.     ULONG                bufferstate;
  552.     ULONG                edgeoffset;
  553.  
  554. // werte check fract : -32767.5 bis 32767.5 => neuer rueckgabe wert !!
  555.  
  556.     /*
  557.     ** Initializing all chunks and theyr sizes and static contents
  558.     */
  559.     setUBYTEArray(name.chunk.name,"NAME",4);
  560.     name.chunk.size = 18;     // fixed size
  561.     setUBYTEArray(name.oname,mesh->name,18);
  562.  
  563.     setUBYTEArray(shp2.chunk.name,"SHP2",4);
  564.     shp2.chunk.size=4;     // fixed size
  565.     shp2.shape=2;            // an axis object
  566.     shp2.lamp=0;            // not a lamp
  567.  
  568.     setUBYTEArray(posi.chunk.name,"POSI",4);
  569.     posi.chunk.size=12;                    // fixed size
  570.     posi.vector.x=float2long(0.0);        // origin of the object is fixed to {0,0,0}
  571.     posi.vector.y=float2long(0.0);
  572.     posi.vector.z=float2long(0.0);
  573.  
  574.     setUBYTEArray(axis.chunk.name,"AXIS",4);
  575.     axis.chunk.size=36;                            // fixed size
  576.     axis.xaxis.x=1,axis.xaxis.y=0,axis.xaxis.z=0;    // fixed x-axis unit vector
  577.     axis.yaxis.x=0,axis.yaxis.y=1,axis.yaxis.z=0;    // fixed y-axis unit vector
  578.     axis.zaxis.x=0,axis.zaxis.y=0,axis.zaxis.z=1;    // fixwd z-axis unit vector
  579.  
  580.     setUBYTEArray(size.chunk.name,"SIZE",4);
  581.     size.chunk.size=12;                                                // fixed size
  582.     size.vector.x=float2long(mesh->bBox.right - mesh->bBox.left);    // bbox length x axis
  583.     size.vector.y=float2long(mesh->bBox.front - mesh->bBox.rear);    // bbox length y axis
  584.     size.vector.z=float2long(mesh->bBox.top - mesh->bBox.bottom);    // bbox length z axis
  585.  
  586.     setUBYTEArray(bbox.chunk.name,"BBOX",4);
  587.     bbox.chunk.size=24;                            // fixed size
  588.     bbox.mins.x=float2long(mesh->bBox.left);        // bbox min x size
  589.     bbox.mins.y=float2long(mesh->bBox.rear);        // bbox min y size
  590.     bbox.mins.z=float2long(mesh->bBox.bottom);    // bbox min z size
  591.     bbox.maxs.x=float2long(mesh->bBox.right);        // bbox max x size
  592.     bbox.maxs.y=float2long(mesh->bBox.front);        // bbox max y size
  593.     bbox.maxs.z=float2long(mesh->bBox.top);        // bbox max z size
  594.  
  595.     setUBYTEArray(pnt2.chunk.name,"PNT2",4);
  596.     // number of points = number of vertices
  597.     pnt2.count=mesh->vertices.numberOfVertices;
  598.     pnt2.chunk.size=sizeof(pnt2.count) + pnt2.count * sizeof(TDDDVector);    
  599.  
  600.     // number of faces = sum of each polygon (number of vertices - 2)
  601.     // number of edges = sum of each polygon ((number of vertices-3)*2 +3)
  602.     fac2.count=0;
  603.     edg2.count=0;
  604.       if(mesh->polygons.firstNode!=NULL) {                 
  605.         pln=mesh->polygons.firstNode;
  606.         do {
  607.             // we accept only polygons with 3 or more points !
  608.             if (pln->numberOfVertices>=3) {
  609.                 fac2.count+=pln->numberOfVertices-2;
  610.                 edg2.count+=(pln->numberOfVertices-3)*2+3;
  611.             }
  612.             pln=pln->next;
  613.         } while (pln!=NULL);
  614.     } 
  615.  
  616.     setUBYTEArray(fac2.chunk.name,"FAC2",4);
  617.     fac2.chunk.size=sizeof(fac2.count) + fac2.count * 3 * sizeof(ULONG);
  618.     
  619.     setUBYTEArray(edg2.chunk.name,"EDG2",4);
  620.     edg2.chunk.size=sizeof(edg2.count) + edg2.count * 2 * sizeof(ULONG);
  621.  
  622.     setUBYTEArray(colr.chunk.name,"COLR",4);
  623.     colr.chunk.size=4;                    // fixed size
  624.     colr.pad=0;                        // default value
  625.     colr.r=255,colr.g=255,colr.b=255;    // default color is white
  626.  
  627.     setUBYTEArray(refl.chunk.name,"REFL",4);
  628.     refl.chunk.size=4;                        // fixed size
  629.     refl.pad=0;                            // default value
  630.     refl.r=0,colr.g=0,colr.b=0;            // default reflection is black
  631.  
  632.     setUBYTEArray(tran.chunk.name,"TRAN",4);
  633.     tran.chunk.size=4;                        // fixed size
  634.     tran.pad=0;                            // default value
  635.     tran.r=0,colr.g=0,colr.b=0;            // default transparency is none
  636.  
  637.     setUBYTEArray(spc2.chunk.name,"SPC2",4);
  638.     spc2.chunk.size=4;                    // fixed size
  639.     spc2.pad=0;                        // default value
  640.     spc2.r=255,colr.g=255,colr.b=255;    // default specularity is white
  641.  
  642.     setUBYTEArray(cls2.chunk.name,"CLS2",4);
  643.     // each face has its color so count = #faces
  644.     cls2.count=fac2.count;
  645.     cls2.chunk.size=sizeof(cls2.count) + cls2.count * 3 * sizeof(UBYTE);
  646.     // if an odd we have an odd count, size must be incremented to insert a pad
  647.     if (cls2.count%2) cls2.chunk.size++;
  648.  
  649.     setUBYTEArray(tls2.chunk.name,"TLS2",4);
  650.     // each face has its transparency so count = #faces
  651.     tls2.count=fac2.count;
  652.     tls2.chunk.size=sizeof(tls2.count) + tls2.count * 3 * sizeof(UBYTE);
  653.     // if an odd we have an odd count, size must be incremented to insert a pad
  654.     if (tls2.count%2) tls2.chunk.size++;
  655.  
  656.     setUBYTEArray(desc.name,"DESC",4);
  657.     // size = sizes of all above and the size of them selves, = 8 Bytes each
  658.     // pnt2,edg2,fac2 only if there are polygons and edges and faces
  659.     // cls2,tls2 only if there are materials and faces
  660.     
  661.     desc.size = name.chunk.size+axis.chunk.size+shp2.chunk.size+posi.chunk.size+size.chunk.size;
  662.     desc.size += bbox.chunk.size+colr.chunk.size+refl.chunk.size+tran.chunk.size+spc2.chunk.size;
  663.     desc.size += 10 * 8;
  664.  
  665.     if(mesh->polygons.firstNode && edg2.count && fac2.count) {
  666.         desc.size += pnt2.chunk.size+edg2.chunk.size+fac2.chunk.size;
  667.         desc.size += 3 * 8;
  668.     }
  669.     if(mesh->materials.firstNode && fac2.count) {
  670.         desc.size += cls2.chunk.size+tls2.chunk.size;
  671.         desc.size += 2 * 8;
  672.     }
  673.  
  674.     setUBYTEArray(obj.name,"OBJ ",4);
  675.     // size = desc.size + 8 for desc itself and 8 for tobj
  676.     obj.size = desc.size + 16;
  677.  
  678.     setUBYTEArray(form.name,"FORM",4);
  679.     // size = obj.size + 8 for obj itself and 4 for tddd
  680.     form.size = obj.size + 12;
  681.  
  682.     setUBYTEArray(tobj.name,"TOBJ",4);
  683.     tobj.size=0;        // fixed size
  684.  
  685.  
  686.     /*
  687.     ** Writing the chunks and theyr dynamic content
  688.     */
  689.     if(FWrite(tdddfile,&form,sizeof(form),1)!=1) return(RCWRITEDATA);
  690.  
  691.     if(FWrite(tdddfile,"TDDD",1,4)!=4) return(RCWRITEDATA);
  692.     
  693.     if(FWrite(tdddfile,&obj,sizeof(obj),1)!=1) return(RCWRITEDATA);
  694.     
  695.     if(FWrite(tdddfile,&desc,sizeof(desc),1)!=1) return(RCWRITEDATA);
  696.  
  697.     if(FWrite(tdddfile,&name,sizeof(name),1)!=1) return(RCWRITEDATA);
  698.  
  699.     if(FWrite(tdddfile,&shp2,sizeof(shp2),1)!=1) return(RCWRITEDATA);
  700.  
  701.     if(FWrite(tdddfile,&posi,sizeof(posi),1)!=1) return(RCWRITEDATA);    
  702.  
  703.     if(FWrite(tdddfile,&axis,sizeof(axis),1)!=1) return(RCWRITEDATA);    
  704.  
  705.     if(FWrite(tdddfile,&size,sizeof(size),1)!=1) return(RCWRITEDATA);    
  706.     
  707.     if(FWrite(tdddfile,&bbox,sizeof(bbox),1)!=1) return(RCWRITEDATA);    
  708.  
  709.     // only if there are polygons to write and edges and faces
  710.     if (mesh->polygons.firstNode && edg2.count && fac2.count) {
  711.         if(FWrite(tdddfile,&pnt2,sizeof(pnt2),1)!=1) return(RCWRITEDATA);    
  712.  
  713.         // initialize the buffer state
  714.         bufferstate=0;
  715.  
  716.         // write the points
  717.         // this is a futil test but anyway
  718.         if(mesh->vertices.firstNode!=NULL) {
  719.             ver=mesh->vertices.firstNode;
  720.             do {
  721.                 TOCLVertex v=ver->vertex;
  722.  
  723.                 vbuffer[bufferstate].x=float2long(v.x);
  724.                 vbuffer[bufferstate].y=float2long(v.y);
  725.                 vbuffer[bufferstate].z=float2long(v.z);
  726.  
  727.                 // increment the bufferstate and 
  728.                 // check if the buffer is full and write and initialize it
  729.                 if (++bufferstate==Ci_BUFFERV) {
  730.                     if(FWrite(tdddfile,&vbuffer,Ci_BUFFERV*sizeof(TDDDVector),1)!=1) return(RCWRITEDATA);
  731.                     bufferstate=0;
  732.                 }
  733.                 
  734.                 ver=ver->next;
  735.             } while(ver!=NULL);
  736.         
  737.             // write the rest of the buffer if there is any
  738.             if (bufferstate!=0) {
  739.                 if(FWrite(tdddfile,&vbuffer,bufferstate*sizeof(TDDDVector),1)!=1) return(RCWRITEDATA);
  740.             }            
  741.         }
  742.  
  743.         if(FWrite(tdddfile,&edg2,sizeof(edg2),1)!=1) return(RCWRITEDATA);    
  744.     
  745.         // initialize the buffer state
  746.         bufferstate=0;
  747.  
  748.             pln=mesh->polygons.firstNode;
  749.         do {                                
  750.             // only if there are 3 or more points in the polygon
  751.             if(pln->numberOfVertices>=3) {
  752.                 plv1=pln->firstNode;
  753.             
  754.                 plvi=plv1;
  755.                 do {    
  756.                     plv2=plvi->next;
  757.                     plv3=plv2->next;
  758.                 
  759.                     ebuffer[bufferstate++]=plv1->vertexNode->index-1;
  760.                     ebuffer[bufferstate++]=plv2->vertexNode->index-1;
  761.                     ebuffer[bufferstate++]=plv2->vertexNode->index-1;
  762.                     ebuffer[bufferstate++]=plv3->vertexNode->index-1;
  763.  
  764.                     // check if the buffer is full and write and initialize it
  765.                     if (bufferstate==Ci_BUFFERE) {
  766.                         if(FWrite(tdddfile,&ebuffer,Ci_BUFFERE*sizeof(ULONG),1)!=1) return(RCWRITEDATA);                      
  767.                         bufferstate=0;
  768.                     }
  769.                 
  770.                     plvi=plvi->next;
  771.                 } while(plv3->next!=NULL);    
  772.                     
  773.                 ebuffer[bufferstate++]=plv1->vertexNode->index-1;
  774.                 ebuffer[bufferstate++]=plv3->vertexNode->index-1;
  775.  
  776.                 // write the rest of the buffer
  777.                 if(FWrite(tdddfile,&ebuffer,bufferstate*sizeof(ULONG),1)!=1) return(RCWRITEDATA);                      
  778.                 bufferstate=0;
  779.             }
  780.             pln=pln->next;
  781.         } while(pln!=NULL);
  782.   
  783.         if(FWrite(tdddfile,&fac2,sizeof(fac2),1)!=1) return(RCWRITEDATA);    
  784.  
  785.         // initialize the buffer state
  786.         bufferstate=0;
  787.  
  788.         // initialize the edge offset
  789.         edgeoffset=0;
  790.  
  791.             pln=mesh->polygons.firstNode;
  792.         do {                                
  793.             ULONG i;
  794.             
  795.             // only if there are 3 or more points in the polygon
  796.             if(pln->numberOfVertices>=3) {
  797.                   // do this for each edge - 1
  798.                 for(i=0;i<((pln->numberOfVertices-3)*2+2);i+=2) {
  799.                     fbuffer[bufferstate++]=edgeoffset+i;
  800.                     fbuffer[bufferstate++]=edgeoffset+i+1;
  801.                     fbuffer[bufferstate++]=edgeoffset+i+2;
  802.                     
  803.                     // check if the buffer is full and write and initialize it
  804.                     if (bufferstate==Ci_BUFFERF) {
  805.                         if(FWrite(tdddfile,&fbuffer,Ci_BUFFERF*sizeof(ULONG),1)!=1) return(RCWRITEDATA);                      
  806.                         bufferstate=0;
  807.                     }
  808.                 }
  809.                 edgeoffset+=i+1;
  810.             }
  811.             pln=pln->next;
  812.         } while(pln!=NULL);
  813.  
  814.         // write he rest of the buffer if there is any
  815.         if (bufferstate!=0) {
  816.             if(FWrite(tdddfile,&fbuffer,bufferstate*sizeof(ULONG),1)!=1) return(RCWRITEDATA);                      
  817.             bufferstate=0;
  818.         }
  819.     }
  820.     
  821.     if(FWrite(tdddfile,&colr,sizeof(colr),1)!=1) return(RCWRITEDATA);
  822.  
  823.     if(FWrite(tdddfile,&refl,sizeof(refl),1)!=1) return(RCWRITEDATA);
  824.  
  825.     if(FWrite(tdddfile,&tran,sizeof(tran),1)!=1) return(RCWRITEDATA);
  826.     
  827.     if(FWrite(tdddfile,&spc2,sizeof(spc2),1)!=1) return(RCWRITEDATA);
  828.     
  829.     // writing the materials if there are some and faces
  830.     if(mesh->materials.firstNode && fac2.count) {
  831.         if(FWrite(tdddfile,&cls2,sizeof(cls2),1)!=1) return(RCWRITEDATA);          
  832.  
  833.         // initialize the buffer state
  834.         bufferstate=0;
  835.  
  836.         // The diffuse color, per face
  837.         pln=mesh->polygons.firstNode;
  838.         do {
  839.             TOCLColor col=pln->materialNode->diffuseColor;
  840.  
  841.             // we accept only polygons with 3 or more points !
  842.             if (pln->numberOfVertices>=3) {
  843.                 ULONG i;
  844.                 
  845.                 for(i=0;i<(pln->numberOfVertices-2);i++) {
  846.                     bbuffer[bufferstate++]=col.r;
  847.                     bbuffer[bufferstate++]=col.g;
  848.                     bbuffer[bufferstate++]=col.b;
  849.  
  850.                     // check if the buffer is full and write and initialize it
  851.                     if (bufferstate==Ci_BUFFERC) {
  852.                         if(FWrite(tdddfile,&bbuffer,Ci_BUFFERC*sizeof(UBYTE),1)!=1) return(RCWRITEDATA);
  853.                         bufferstate=0;
  854.                     }
  855.                 }
  856.             }
  857.                         
  858.             pln=pln->next;
  859.         } while(pln!=NULL);
  860.  
  861.         // if we have an odd count a pad has to be added at the end
  862.         if (cls2.count%2) {
  863.             bbuffer[bufferstate++]=0;
  864.         }
  865.  
  866.  
  867.         // write the rest of the buffer if any
  868.         if (bufferstate!=0) {
  869.             if(FWrite(tdddfile,&bbuffer,bufferstate*sizeof(UBYTE),1)!=1) return(RCWRITEDATA);
  870.             bufferstate=0;
  871.         }
  872.  
  873.         if(FWrite(tdddfile,&tls2,sizeof(tls2),1)!=1) return(RCWRITEDATA);          
  874.  
  875.         // initialize the buffer state
  876.         bufferstate=0;
  877.  
  878.         // The transparency, per face
  879.         pln=mesh->polygons.firstNode;
  880.         do {
  881.             // we accept only polygons with 3 or more points !
  882.             if (pln->numberOfVertices>=3) {
  883.                 ULONG i;
  884.                 
  885.                 for(i=0;i<(pln->numberOfVertices-2);i++) {  
  886.                     bbuffer[bufferstate++]=UBYTE(255*mat->transparency);
  887.                     bbuffer[bufferstate++]=UBYTE(255*mat->transparency);
  888.                     bbuffer[bufferstate++]=UBYTE(255*mat->transparency);
  889.  
  890.                     // check if the buffer is full and write and initialize it
  891.                     if (bufferstate==Ci_BUFFERC) {
  892.                         if(FWrite(tdddfile,&bbuffer,Ci_BUFFERC*sizeof(UBYTE),1)!=1) return(RCWRITEDATA);
  893.                         bufferstate=0;
  894.                     }
  895.                 }
  896.             }
  897.             
  898.             pln=pln->next;
  899.         } while(pln!=NULL);
  900.  
  901.         // if we have an odd count a pad has to be added at the end
  902.         if (tls2.count%2) {
  903.             bbuffer[bufferstate++]=0;
  904.         }
  905.         
  906.         // write the rest of the buffer if any
  907.         if (bufferstate!=0) {
  908.             if(FWrite(tdddfile,&bbuffer,bufferstate*sizeof(UBYTE),1)!=1) return(RCWRITEDATA);
  909.             bufferstate=0;
  910.         }
  911.     }
  912.  
  913.     if(FWrite(tdddfile,&tobj,sizeof(tobj),1)!=1) return(RCWRITEDATA);
  914.   
  915.     return(RCNOERROR);
  916. }
  917.  
  918. /************************* End of file ******************************/
  919.